﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using Microsoft.Health;
using Microsoft.Health.ItemTypes;
using FusionAPI;

namespace PFSync
{
    /// <summary>
    /// Summary description for Height
    /// </summary>
    public class SyncGlucose : SyncItem
    {
        public SyncGlucose()
        { }

        private object itemValue;

        #region Properties
        /// <summary>
        /// Returns a hashcode that is the unique ID for this item
        /// </summary>
        public override int ID
        {
            get
            {
                int hashCode = DateAdded.GetHashCode();
                hashCode += Value.GetHashCode();
                hashCode += Measurement.GetHashCode();

                return hashCode;
            }
        }

        /// <summary>
        /// Generate a HealthVault item based on the Value,
        /// Date, and Measurements stored in this object
        /// </summary>
        public override HealthRecordItem HVItem
        {
            get
            {
                DisplayValue value;

                BloodGlucose item = new BloodGlucose();
                item.When = new HealthServiceDateTime(DateAdded);

                // Get the display value to store based on the measurement type
                if (Measurement == MeasurementType.Millimoles)
                    value = new DisplayValue(Convert.ToDouble(itemValue), "mmol/L", "mmol-per-l");
                else
                    value = new DisplayValue(Convert.ToDouble(Value), "mg/dL", "mg-per-dl");

                // Store the item's value based on itemValue (meters) and the display value
                item.Value = new BloodGlucoseMeasurement(Convert.ToDouble(itemValue), value);
                item.CommonData.Source = "PatientFusion Sync";
                item.GlucoseMeasurementType = new CodableValue("Plasma");

                return item;
            }
        }

        /// <summary>
        /// Generate a PracticeFusion item based on the Value,
        /// Date, and Measurements stored in this object
        /// </summary>
        public override ClinicalDataValue PFItem
        {
            get
            {
                ClinicalDataValue item = new ClinicalDataValue();
                item.CollectedDateTime = DateAdded.ToUniversalTime();
                item.Value = Value.ToString();
                item.Source = "PatientFusion Sync";
                item.ID = PFTypeId;

                return item;
            }
        }

        /// <summary>
        /// Return the Practice Fusion TypeID
        /// </summary>
        public override int PFTypeId
        {
            get
            {
                if (Measurement == MeasurementType.Milligrams)
                    return 59;
                else
                    return 60;
            }
        }

        /// <summary>
        /// Return the HealthVault Type GUID
        /// </summary>
        public override Guid HVTypeID
        {
            get { return BloodGlucose.TypeId; }
        }

        /// <summary>
        /// Gets and sets the Glucose value
        /// </summary>
        public override object Value
        {
            get
            {
                // If MeasurementType equals Millimoles, return value
                if (Measurement == MeasurementType.Millimoles)
                    return itemValue;

                // Else, return the value in Milligrams
                else
                    return Math.Round(Convert.ToDouble(itemValue) * (1 / 0.02586), 4);
            }

            set { itemValue = value; }
        }

        /// <summary>
        /// Gets and sets the object's measurement type
        /// </summary>
        public override MeasurementType Measurement { get; set; }

        /// <summary>
        /// Gets and sets the object's Date
        /// </summary>
        public override DateTime DateAdded { get; set; }
        #endregion

        /// <summary>
        /// Default constructor takes in a date, value and measurement
        /// </summary>
        /// <param name="date">Date Added</param>
        /// <param name="value">Value of Height</param>
        /// <param name="measurement">Height Measurement</param>
        public SyncGlucose(DateTime date, double value, MeasurementType measurement)
        {
            DateAdded = date;
            Measurement = measurement;
            
            // If the value given was in milligrams
            if (measurement == MeasurementType.Milligrams)
                itemValue = value / (1 / 0.02586);
            else
                itemValue = value;
        }

        /// <summary>
        /// Constructor takes in a HealthVault BloodGlucose item
        /// and converts it to a PFSync item.
        /// </summary>
        /// <param name="hvRecord">HealthVault BloodGlucose</param>
        public SyncGlucose(BloodGlucose hvRecord)
        {
            DateAdded = hvRecord.When.ToDateTime();
            

            // Check to see if the value given is in millimoles or milligrams
            if (hvRecord.Value.DisplayValue.UnitsCode == "mmol-per-l")
            {
                Measurement = MeasurementType.Millimoles;
                Value = hvRecord.Value.Value;
            }
            else
            {
                Measurement = MeasurementType.Milligrams;
                Value = hvRecord.Value.DisplayValue.Value / (1 / 0.02586);
            }
        }

        /// <summary>
        /// Constructor takes in a PracticeFusion Record and a
        /// measurement type and converts it to a PFSync Item
        /// </summary>
        /// <param name="pfRecord">PracticeFusion Record</param>
        /// <param name="measurement">Measurement Type</param>
        public SyncGlucose(ClinicalDataValue pfRecord, MeasurementType measurement)
        {
            DateAdded = pfRecord.CollectedDateTime.ToLocalTime();
            Measurement = measurement;

            // If the measurement type is in milligrams, convert to millimoles
            if (measurement == MeasurementType.Millimoles)
                Value = double.Parse(pfRecord.Value);
            else
                Value = double.Parse(pfRecord.Value) / (1 / 0.02586);
        }
    }
}
